import time
from datetime import datetime, timedelta
from utils import *
from 相机位置 import KAKO_DATA_LIST_UP, KAKO_DATA_LIST_DOWN
# Format = '%Y-%m-%d %H:%M:%S.%f'


def pre(dist_t):
    new_dict = {}
    for key, value in dist_t.items():
        for i in range(len(value)):
            if i == 0:
                new_dict[key] = value[i]
            else:
                new_key = key + f"-{i}"
                new_dict[new_key] = value[i]
    return new_dict


def moa_to_list(moa_file):
    encoding = get_encoding(moa_file)
    try:
        data = pd.read_csv(moa_file, encoding=encoding)
    except UnicodeDecodeError:
        print("无法读取文件，请检查文件编码")
        raise
    data_dict = data.to_dict(orient='records')
    return data_dict


def match_plate(dict_data, flag):
    dict_data = pre(dict_data)
    vlp_gid = {}
    possible_error = {}
    gid_miss = {}
    gid_complete = {}
    final_data = {}
    key_list = list(dict_data.keys())
    for key, value in dict_data.items():
        vlp_gid[key] = list(value.keys())
    for k, v in vlp_gid.items():
        if len(v) == 1:
            if v[0] not in possible_error:
                possible_error[v[0]] = []
            possible_error[v[0]].append(k)
        elif len(v) == len(flag):
            gid_complete[k] = dict_data[k]
            gid_complete[k]["flag"] = 0
        else:
            diff = [item for item in flag if item not in v]
            for d in diff:
                if d not in gid_miss:
                    gid_miss[d] = []
                gid_miss[d].append(k)
    # print("可能匹配错误：", len(gid_miss.keys()), time.time())
    for k1, v1 in possible_error.items():
        print(k1, v1, time.time())
        for vlp in v1:
            max_fen = 0
            max_vlpp = None
            for vlpp in gid_miss[k1]:
                original_vlp = vlp.split('-')[0]
                original_vlpp = vlpp.split('-')[0]
                fenshu = n_calc_plate_match_point(original_vlp, original_vlpp, type_=1)
                if fenshu >= 72:
                    # 若匹配上，计算时间是否合适
                    min_t = max_t = False
                    time_vlp = parse_time(dict_data[vlp][k1])
                    index_vlp = flag.index(k1)
                    time_vlpp_dict = dict_data[vlpp]
                    for i in range(index_vlp-1, -1, -1):
                        if flag[i] in time_vlpp_dict.keys():
                            time_vlpp = parse_time(time_vlpp_dict[flag[i]])
                            if timedelta(minutes=(0.5*(index_vlp-i))) <= (time_vlp - time_vlpp) <= timedelta(minutes=(5*(index_vlp-i))):
                                min_t = False
                            else:
                                min_t = True
                            break
                    for i in range(index_vlp+1, len(flag)):
                        if flag[i] in time_vlpp_dict.keys():
                            time_vlpp = parse_time(time_vlpp_dict[flag[i]])
                            if timedelta(minutes=(0.5*(i-index_vlp))) <= (time_vlpp - time_vlp) <= timedelta(minutes=(5*(i-index_vlp))):
                                max_t = False
                            else:
                                max_t = True
                            break
                    if max_t or min_t:
                        # print(vlp, vlpp, time_vlpp_dict, dict_data[vlp])
                        continue
                    else:
                        if fenshu > max_fen:
                            max_fen = fenshu
                            max_vlpp = vlpp

            if max_vlpp is not None:
                gid_complete[max_vlpp] = dict_data[max_vlpp]
                gid_complete[max_vlpp][k1] = dict_data[vlp][k1]
                gid_complete[max_vlpp]["flag"] = f"{k1}-{vlp.split('-')[0]}"
                key_list.remove(vlp)

    for kk, vv in dict_data.items():
        if kk in key_list:
            final_data[kk] = vv

    return final_data


def match_moa(dict_data, moa_data, flag, flag_dist):
    if not moa_data:
        print("无默A00000数据")
        return {}
    dict_data = pre(dict_data)
    for k, v in dict_data.items():
        v_list = list(dict_data[k].keys())
        diff = [item for item in flag if item not in v_list]
        for d in diff:
            index = flag.index(d)
            best_score = -1
            best_moa_index = -1
            for m in range(len(moa_data)):
                moa = moa_data[m]
                if moa['gantryid'] == d:
                    min_t = max_t = False
                    min_transtime = None
                    max_transtime = None
                    min_index = 0
                    max_index = 0
                    moa_time = parse_time(moa['transtime'])
                    for i in range(index - 1, -1, -1):
                        if flag[i] in dict_data[k].keys():
                            time_vlp = parse_time(dict_data[k][flag[i]])
                            if timedelta(minutes=(0.5 * (index - i))) <= (moa_time - time_vlp) <= timedelta(
                                    minutes=(5 * (index - i))):
                                min_t = False
                                min_transtime = time_vlp
                                min_index = i
                            else:
                                min_t = True
                            # 找到前面一个就退出
                            break
                    for i in range(index + 1, len(flag)):
                        if flag[i] in dict_data[k].keys():
                            time_vlp = parse_time(dict_data[k][flag[i]])
                            if timedelta(minutes=(0.5 * (i - index))) <= (time_vlp - moa_time) <= timedelta(
                                    minutes=(5 * (i - index))):
                                max_t = False
                                max_transtime = time_vlp
                                max_index = i
                            else:
                                max_t = True
                            # 找到后面一个就退出
                            break
                    if max_t or min_t:
                        # print(vlp, vlpp, time_vlpp_dict, dict_data[vlp])
                        continue
                    else:
                        score_min = score_max = 0
                        if min_transtime is not None:
                            dist = 0
                            for i in range(min_index, index):
                                dist += flag_dist[i]
                            t = dist / 80 * 3.6 / 60 # 分钟
                            expec_time = min_transtime + timedelta(minutes=t)
                            score_min = n_calc_time_match_point(moa_time, expec_time, expec_time-min_transtime)
                        if max_transtime is not None:
                            dist = 0
                            for i in range(index, max_index):
                                dist += flag_dist[i]
                            t = dist / 80 * 3.6 / 60  # 分钟
                            expec_time = max_transtime - timedelta(minutes=t)
                            score_max = n_calc_time_match_point(moa_time, expec_time, max_transtime-expec_time)
                        if best_score < (score_min + score_max):
                            best_score = score_min + score_max
                            best_moa_index = m
            if best_moa_index != -1:
                dict_data[k][d] = moa_data[best_moa_index]['transtime']
                if 'flag' in dict_data[k].keys():
                    dict_data[k]['flag'] += f"-{d}-默A00000-{moa_data[best_moa_index]['transtime']}-{best_score}"
                else:
                    dict_data[k]['flag'] = f"{d}-默A00000-{moa_data[best_moa_index]['transtime']}-{best_score}"
                del moa_data[best_moa_index]

    for k, v in dict_data.items():
        v_list = list(v.keys())
        diff = [item for item in flag if item not in v_list]
        dict_data[k]['null'] = f"{len(diff)}"
        for d in diff:
            dict_data[k]['null'] += f"-{d}"

    return dict_data, moa_data


def main_data(input_folder, output_folder, flag=True):
    up = list(KAKO_DATA_LIST_UP.keys())
    down = list(KAKO_DATA_LIST_DOWN.keys())
    up_dist = []
    for i in range(len(up) - 1):
        up_dist.append(KAKO_DATA_LIST_UP[up[i]]['Downstream']['dis'])
    down_dist = []
    for i in range(len(down) - 1):
        down_dist.append(KAKO_DATA_LIST_DOWN[down[i]]['Downstream']['dis'])

    if flag:
        # 车牌匹配
        input_file_up = os.path.join(input_folder, 'output_up.csv')
        save_path_up = os.path.join(output_folder, 'output_up_match_plate.csv')

        csv_dict_data = csv_to_dict(input_file_up)
        t2 = time.time()
        new_dict = match_plate(csv_dict_data, up)
        t3 = time.time()
        print("车牌匹配耗时", t3 - t2)
        save_dict_csv(new_dict, up, save_path_up)

        # 默A匹配
        moa_file = os.path.join(input_folder, 'output_默A.csv')
        input_file = os.path.join(input_folder, 'output_up_match_plate.csv')
        save_path = os.path.join(output_folder, 'output_up_match_moa.csv')
        sorted_path = os.path.join(output_folder, 'output_up_sorted.csv')

        csv_dict_data = csv_to_dict(input_file)
        moa_list_data = moa_to_list(moa_file)

        new_dict, new_moa_data = match_moa(csv_dict_data, moa_list_data, up, up_dist)

        save_dict_csv(new_dict, up, save_path)

        save_csv(new_moa_data, os.path.join(output_folder, 'output_默A_temp.csv'))

        sorted_data(save_path, sorted_path)
    else:
        # 车牌匹配
        input_file_down = os.path.join(input_folder, 'output_down.csv')
        save_path_down = os.path.join(output_folder, 'output_down_match_plate.csv')

        csv_dict_data = csv_to_dict(input_file_down)
        t2 = time.time()
        new_dict = match_plate(csv_dict_data, down)
        t3 = time.time()
        print("匹配", t3 - t2)
        save_dict_csv(new_dict, down, save_path_down)

        # 默A匹配
        moa_file = os.path.join(input_folder, 'output_默A_temp.csv')
        input_file = os.path.join(input_folder, 'output_down_match_plate.csv')
        save_path = os.path.join(output_folder, 'output_down_match_moa.csv')
        sorted_path = os.path.join(output_folder, 'output_down_sorted.csv')

        csv_dict_data = csv_to_dict(input_file)
        moa_list_data = moa_to_list(moa_file)

        new_dict, new_moa_data = match_moa(csv_dict_data, moa_list_data, down, down_dist)

        save_dict_csv(new_dict, down, save_path)

        save_csv(new_moa_data, os.path.join(output_folder, 'output_new_默A.csv'))

        sorted_data(save_path, sorted_path)


if __name__ == '__main__':
    # input_path = r'D:\GJ\项目\铜锣山\output\2025-01-24'
    # output_path = r'D:\GJ\项目\铜锣山\output\2025-01-24'
    #
    # main(input_path, output_path, True)
    # main(input_path, output_path, False)
    # f_list = ['2025-01-24', '2025-01-25', '2025-01-26', '2025-01-27', '2025-01-28', '2025-01-29', '2025-01-30', '2025-01-31', '2025-02-01', '2025-02-02', '2025-02-03', '2025-02-04', '2025-02-05', '2025-02-06']
    # f_list = ['2025-01-26', '2025-01-27', '2025-01-28', '2025-01-29', '2025-01-30', '2025-01-31']
    # f_list = ['2025-02-01', '2025-02-02', '2025-02-03', '2025-02-04', '2025-02-05', '2025-02-06']
    # f_list = ['2025-02-07', '2025-02-08', '2025-02-09', '2025-02-10', '2025-02-11', '2025-02-12', '2025-02-13',
    #           '2025-02-14', '2025-02-15', '2025-02-16', '2025-02-17', '2025-02-18', '2025-02-19', '2025-02-20',
    #           '2025-02-20', '2025-02-21', '2025-02-22', '2025-02-23', '2025-02-24']
    f_list = ['2025-02-20']
    for ff in f_list:
        # 示例：遍历当前目录下的 'example_folder' 文件夹
        input_path = os.path.join(r'D:\GJ\项目\事故检测\模拟数据\output_1', ff)
        output_path = os.path.join(r'D:\GJ\项目\事故检测\模拟数据\output_1', ff)

        main_data(input_path, output_path, True)
        # main_data(input_path, output_path, False)





    # up = list(KAKO_DATA_LIST_UP.keys())
    # down = list(KAKO_DATA_LIST_DOWN.keys())
    # up_dist = []
    # for i in range(len(up) - 1):
    #     up_dist.append(KAKO_DATA_LIST_UP[up[i]]['Downstream']['dis'])
    # down_dist = []
    # for i in range(len(down) - 1):
    #     down_dist.append(KAKO_DATA_LIST_DOWN[down[i]]['Downstream']['dis'])

    # input_file = os.path.join(input_path, 'output_up.csv')
    # save_path = os.path.join(output_path, 'output_up_0303.csv')

    # t1 = time.time()
    # print("读取文件", t1)
    # csv_dict_data = csv_to_dict(input_file)
    # t2 = time.time()
    # print("读取文件", t2-t1)
    # new_dict = match_plate(csv_dict_data, up)
    # t3 = time.time()
    # print("匹配", t3-t2)
    # save_dict_csv(new_dict, up, save_path)
    # t4 = time.time()
    # print(t4-t3, t3-t2, t2-t1)

    # moa_file = os.path.join(input_path, 'output_默A.csv')
    # input_file = os.path.join(input_path, 'output_up_0303.csv')
    # save_path = os.path.join(output_path, 'output_up_0303_2.csv')
    # sorted_path = os.path.join(output_path, 'output_up_0303_sorted.csv')
    #
    # csv_dict_data = csv_to_dict(input_file)
    # moa_list_data = moa_to_list(moa_file)
    #
    # new_dict, new_moa_data = match_moa(csv_dict_data, moa_list_data, up, up_dist)
    #
    # save_dict_csv(new_dict, up, save_path)
    # save_csv(new_moa_data, os.path.join(output_path, 'output_new_默A_1.csv'))
    #
    # sorted_data(save_path, sorted_path)
